#!/bin/sh

if [ -n "$_VL_IMPORT_STEP_DEP" ] ; then
	return 0;
fi
_VL_IMPORT_STEP_DEP=0

# 加载项目环境
if ! load "$VL_ENV" ; then
	return 1;
fi

# 检查是否需要配置项目依赖, 如果需要则进行依赖配置
# 
# 返回值 : 配置成功返回 0
function checkDependencies() {
	if ! isVLStyleProject ; then
		printWarn "Not a vl-style project ... ignore check dependencies"
		return 0
	fi

	if ! checkVariable "$VL_DEP" ; then
		# 项目不存在依赖
		echo "remove all denpendencies ..."
		removeAllDependencies
		return $?
	fi

	if checkFileExpire "$VL_CACHE_FILE_DEP_TS" "$VL_FILE_DEP" || checkVariable "$VL_ARG_FORCE_DEP" ; then
		echo "config denpendencies ..."
		configDependencies
		return $?
	fi

	return 0
}

# 配置项目依赖
#
# 返回值 : 配置成功返回 0
function configDependencies() {
	# 创建依赖文件
	local depArr=($VL_DEP)
	local idx=0
	local count=${#depArr[@]}
	if [[ `expr $count % 4` -ne 0 ]] ; then
		printError "VL_DEP is not valid"
		return 1
	fi
	while ((idx <= count - 4))
	do
		local mode=0
		case "${depArr[idx + 3]}" in
		static)
			mode=1
		;;
		dynamic)
			mode=2
		;;
		header)
			mode=3
		;;
		*)
			printError "Unsupport compile mode : ${depArr[idx + 3]}"
			return 1
		;;
		esac
		if [[ $idx -eq 0 ]] ; then
			echo "${depArr[idx]} ${depArr[idx + 1]} ${depArr[idx + 2]} $mode" > vl_dep
		else
			echo "${depArr[idx]} ${depArr[idx + 1]} ${depArr[idx + 2]} $mode" >> vl_dep
		fi
		let idx+=4
	done

	# 加载依赖生成脚本
	if ! load "$VL_ENV_PART_GENERATE_FOR_DEP" ; then
		return 1
	fi

	# 生成第三方目录
	if ! checkDirOrCreate "$VL_DIR_DEP" ; then
		printError "create \"$VL_DIR_DEP\" failed..."
		return 1
	fi

	# 重新生成下载临时目录
	if ! removeFile "$VL_DIR_DEP_TEMP" ; then
		printError "delete \"$VL_DIR_DEP_TEMP\" failed..."
		return 1
	fi
	if ! checkDirOrCreate "$VL_DIR_DEP_TEMP" ; then
		printError "create \"$VL_DIR_DEP_TEMP\" failed..."
		return 1
	fi

	# 处理依赖
	if ! processDependencies "$VL_DIR_ROOT" ; then
		removeFile "$VL_DIR_DEP_TEMP"
		return 1
	fi

	# 使用完删除 temp 目录
	if ! removeFile "$VL_DIR_DEP_TEMP" ; then
		printError "delete \"$VL_DIR_DEP_TEMP\" failed..."
		return 1
	fi
	
	# 处理完依赖后, 构建编译顺序文件
	local depCount=$VL_DEP_COMPILE_IDX
	local depIdx=0
	if [ $depCount -ge 0 ] ; then
		local isFirst=0
		while ((depIdx<depCount))
		do
			if [ $isFirst -eq 0 ] ; then
				isFirst=1
				if ! echo "${VL_DEP_COMPILE_ARR[depIdx]}_${VL_DEP_COMPILE_VER[depIdx]} ${VL_DEP_COMPILE_MODE[depIdx]}" > "$VL_CACHE_FILE_DEP_COMPILE_LIST" ; then
					printError "create \"$VL_CACHE_FILE_DEP_COMPILE_LIST\" failed"
					exit 1
				fi
			else
				if ! echo "${VL_DEP_COMPILE_ARR[depIdx]}_${VL_DEP_COMPILE_VER[depIdx]} ${VL_DEP_COMPILE_MODE[depIdx]}" >> "$VL_CACHE_FILE_DEP_COMPILE_LIST" ; then
					printError "create \"$VL_CACHE_FILE_DEP_COMPILE_LIST\" failed"
					exit 1
				fi
			fi
			
			let depIdx++
		done
	fi

	# 依赖配置完成, 生成时间戳文件
	if ! saveFileTs "$VL_CACHE_FILE_DEP_TS" "$VL_FILE_DEP" ; then
		return 1
	fi
}

# 处理项目依赖
# 参数 1 : 项目根目录
# 参数 2 : 依赖名
# 参数 3 : 依赖版本
# 参数 4 : 依赖编译方式
# 
# * 如果只传递参数 1, 表示为宿主项目, 不参与依赖编译配置
#
# 返回值 : 处理成功返回 0
function processDependencies() {
	local projectDir="$1"
	if ! cd "$projectDir" ; then
		printError "cannot move to $projectDir"
		return 1
	fi

	# 先创建工程文件夹
	if ! checkDirOrCreate ".vl-build" ; then
		printError "create \"$projectDir/.vl-build\" dir failed"
		return 1
	fi

	local dep_prefix=""
	local dep_libs=""
	local dep_ldflags=""
	local dep_cppflags=""
	local dep_end_is_static=0

	if checkVariable "$2" ; then
		# 宿主项目不指定 Prefix
		dep_prefix="$VL_DIR_DEP_GEN/$2_$3"
		pushCompileDependency "$2" "$3" "$4"
	fi

	# 检查是否存在 vl_dep 文件
	if checkFile "vl_dep" ; then
		local deps=(`cat vl_dep`)
		declare local idx=0
		declare local count=${#deps[@]}
		if [[ `expr $count % 4` -ne 0 ]] ; then
			printError "$projectDir/vl_dep is not valid"
			return 1
		fi

		# 检查依赖是否存在, 如果不存在则通过 git 下载
		while ((idx<=count - 4))
		do
			local depDir="$VL_DIR_DEP/${deps[idx]}_${deps[idx + 2]}"
			if ! checkDir "$depDir" ; then
				# 不存在对应依赖，下载
				if ! downloadDependency "${deps[idx]}" "${deps[idx + 1]}" "${deps[idx + 2]}" ; then
					return 1
				fi
			fi

			# 处理嵌套依赖
			if ! processDependencies "$depDir" "${deps[idx]}" "${deps[idx + 2]}" "${deps[idx + 3]}" ; then
				return 1
			fi

			if [[ "$VL_OS_TYPE" -eq "$VL_OS_TYPE_MACOS" ]] ; then
				case "${deps[3]}" in
				1)
					# static
					dep_ldflags="$dep_ldflags -L${VL_DIR_DEP_GEN}/${deps[idx]}_${deps[idx + 2]}/slib"
					dep_libs="$dep_libs -l${deps[idx]}"
					dep_cppflags="$dep_cppflags -I${VL_DIR_DEP_GEN}/${deps[idx]}_${deps[idx + 2]}/include"
				;;
				2)
					# dynamic
					dep_ldflags="$dep_ldflags -L${VL_DIR_DEP_GEN}/${deps[idx]}_${deps[idx + 2]}/lib"
					dep_libs="$dep_libs -l${deps[idx]}"
					dep_cppflags="$dep_cppflags -I${VL_DIR_DEP_GEN}/${deps[idx]}_${deps[idx + 2]}/include"
				;;
				3)
					# header
					dep_cppflags="$dep_cppflags -I${VL_DIR_DEP_GEN}/${deps[idx]}_${deps[idx + 2]}/include"
				;;
				*)
					printError "Unsupport link mode : ${deps[3]}"
					return 1
				;;
				esac
			else
				case "${deps[3]}" in
				1)
					# static
					dep_ldflags="$dep_ldflags -L${VL_DIR_DEP_GEN}/${deps[idx]}_${deps[idx + 2]}/slib"
					dep_libs="$dep_libs -Wl,-Bstatic,-l${deps[idx]}"
					dep_ldflags="$dep_ldflags -L${VL_DIR_DEP_GEN}/${deps[idx]}_${deps[idx + 2]}/lib"
					dep_cppflags="$dep_cppflags -I${VL_DIR_DEP_GEN}/${deps[idx]}_${deps[idx + 2]}/include"
					dep_end_is_static=1
				;;
				2)
					# dynamic
					dep_ldflags="$dep_ldflags -L${VL_DIR_DEP_GEN}/${deps[idx]}_${deps[idx + 2]}/lib"
					dep_libs="$dep_libs -Wl,-Bdynamic,-l${deps[idx]}"
					dep_ldflags="$dep_ldflags -L${VL_DIR_DEP_GEN}/${deps[idx]}_${deps[idx + 2]}/lib"
					dep_cppflags="$dep_cppflags -I${VL_DIR_DEP_GEN}/${deps[idx]}_${deps[idx + 2]}/include"
					dep_end_is_static=2
				;;
				3)
					# header
					dep_ldflags="$dep_ldflags -L${VL_DIR_DEP_GEN}/${deps[idx]}_${deps[idx + 2]}/lib"
				;;
				*)
					printError "Unsupport link mode : ${deps[3]}"
					return 1
				;;
				esac
			fi
			let idx+=4
		done

		if [ $dep_end_is_static -eq 1 ] ; then
			dep_libs="$dep_libs -Wl,-Bdynamic"
		fi
	fi

	# 生成编译配置脚本
	if ! generateDepOptions "$projectDir/.vl-build/vl_dep_compile_options" "$dep_prefix" "$dep_libs" "$dep_ldflags" "$dep_cppflags" ; then
		printError "configure dependency \"$2_$3\" failed"
		return 1
	fi


}

# 移除全部依赖相关文件
# 当项目不在需要依赖时，清空全部依赖相关文件
# vl_dep
# .vl-build/vl_dep_ts
# .vl-build/vl-third
# .vl-build/vl_dep_compile_options
# .vl-build/vl_dep_compile_list
function removeAllDependencies() {
	if ! removeFile "$VL_FILE_DEP" ; then
		printError "remove denpendencies failed"
		return 1
	fi

	if ! removeFile "$VL_CACHE_FILE_DEP_TS" ; then
		printError "remove denpendencies failed"
		return 1
	fi

	if ! removeFile "$VL_CACHE_FILE_DEP_COMPILE_LIST" ; then
		printError "remove denpendencies failed"
		return 1
	fi

	if ! removeFile "$VL_CACHE_FILE_DEP_OPTIONS" ; then
		printError "remove denpendencies failed"
		return 1
	fi

	if ! removeFile "$VL_DIR_DEP" ; then
		printError "remove denpendencies failed"
		return 1
	fi

	return 0
}

# 下载项目依赖
# 参数 1 : 依赖名
# 参数 2 : 依赖地址
# 参数 3 : 依赖版本
function downloadDependency() {
	local curLoc=`pwd`
	cd "$VL_DIR_DEP_TEMP"
	echo "git clone --branch $3 $2 ..."
	if ! git clone --branch $3 $2  > /dev/null 2>&1 ; then
		printError "download $1 error ... url : $2"
		return 1
	fi
	
	if ! mv * "$VL_DIR_DEP/$1_$3" ; then
		printError "cannot move to $VL_DIR_DEP/$1_$3"
		return 1
	fi
	cd "$curLoc"
	return 0
}

# 添加编译依赖
# 参数 1 : 依赖名
# 参数 2 : 依赖版本号
# 参数 3 : 编译模式 (1: 静态编译, 2: 动态编译, 3: 静态+动态)
#
# 返回值 : 如果返回 0, 表示需要进行编译
#         如果返回 1, 表示忽略编译
function pushCompileDependency() {
	local idx=0
    for element in "${!VL_DEP_COMPILE_ARR}"; do
        if [[ $element == "$1" ]] && [[ "${VL_DEP_COMPILE_VER[idx]}" == "$2" ]] ; then
			# 找到相同依赖, 且版本相同
			if [[ "${VL_DEP_COMPILE_MODE[idx]}" == "$mode" ]] ; then
				# 模式相同，直接忽略
				return 1
			else
				# 模式不同，修改模式
				VL_DEP_COMPILE_MODE[$idx]="3"
				return 1
			fi
        fi
		let idx++
    done
	VL_DEP_COMPILE_ARR[$VL_DEP_COMPILE_IDX]="$1"
	VL_DEP_COMPILE_VER[$VL_DEP_COMPILE_IDX]="$2"
	VL_DEP_COMPILE_MODE[$VL_DEP_COMPILE_IDX]="$mode"

	let VL_DEP_COMPILE_IDX++
	return 0
}